#pragma once

#include "Common.hpp"

template <class T>
class Memorypool // 定长内存池
{
public:
    T *New()
    {
        T *obj = nullptr;
        if (free_list_) // 如果内存回收链表不为空，直接拿回收链表的空间返回
        {
            void *next = *(void **)free_list_;
            obj = (T *)free_list_;
            free_list_ = next;
        }
        else // 内存回收链表为空，向大内存块申请空间
        {
            // 如果大内存块不够一个T对象大小，则重新开辟大内存块
            if (remain_bytes_ < sizeof(T))
            {
                remain_bytes_ = 128 * 1024;
                // memorypool_ = (char *)malloc(remain_bytes_);
                memorypool_ = (char *)SystemAlloc(remain_bytes_ >> PAGE_SHIFT);
                if (memorypool_ == nullptr)
                {
                    throw std::bad_alloc();
                }
            }

            size_t objsize = sizeof(T) < sizeof(void *) ? sizeof(void *) : sizeof(T);
            obj = (T *)memorypool_;
            memorypool_ += objsize;
            remain_bytes_ -= objsize;
        }
        new (obj) T;
        return obj;
    }

    void Delete(T *obj)
    {
        obj->~T();
        // 放入内存回收链表
        *(void **)obj = free_list_;
        free_list_ = obj;
    }

private:
    char *memorypool_ = nullptr; // 申请的大块内存
    size_t remain_bytes_ = 0;    // 内存池还剩下的内存大小
    void *free_list_ = nullptr;  // 内存回收链表
};